/*
 * Danny Wu 2/9/2014
 */

package post;

/**
 * Post is the register of a store. It is used to process customer initiated 
 * transaction. it can calculate the total and print an invoice of that 
 * transaction.
 * @author Danny
 */

public class Post {

    //the store that this post will process the transaction
    Store store; 
     
    //the current transaction being processed
    Transaction transaction;
    //the total for the current transaction
    double total;
    //the subtotal of each transaction item. Assume a max of 100 items
    double[] transactionItemSubtotal;
    //the total number of transaction processed from the current transaction
    int numTransItemProcessed;
    //the amount paid by the customer and how they paid for it
    IPayment payment;
    //amount return as change to the customer
    double amountReturned;
    
    /**
     * The constructor of this Post.
     * @param newStore the store object this post will process in
     */
    public Post(Store newStore){
        this.store=newStore;
        this.total=0.0;
        this.numTransItemProcessed=0;
        this.transactionItemSubtotal=new double[100];
    }
    
    /**
     * Clears previous transaction information and start on the new
     * transaction that is passed in. Calculates subtotal of each
     * transaction item and total of the whole transaction.
     * @param transaction The new transaction that needs to be processed
     */
    public void newTransaction(Transaction newTransaction){
        //reset the variables 
        this.transaction=newTransaction;
        this.payment=this.transaction.getPayment();
        this.total=0.0;
        this.amountReturned=0.0;
        this.numTransItemProcessed=0;
        //begin processing transaction
        this.processTransaction();
        //calculate amount return. Assume exact payment so no change
        this.amountReturned=0;
        //prints the recipt
        this.printInvoice();
    }
    
    /**
     * iterates through each transaction item and calculated the subtotal, 
     * stores the subtotal, update the total, and increment the number of 
     * transaction processed.
     */
    private void processTransaction(){
        int numberOfTransactionItem=this.transaction.getNumTransItem();
        TransactionItem currentTransactionItem;
        for(int i=0; i<numberOfTransactionItem; i++){
            currentTransactionItem=this.transaction.getTransactionItemsAt(i);
            transactionItemSubtotal[i]=getPrice(currentTransactionItem) * currentTransactionItem.getQuantity();
            this.total+=transactionItemSubtotal[i];
            this.numTransItemProcessed++;
        }
    }
    
    /**
     * Returns the price of the given item
     * @param item The item you wish to get the price for. 
     * @return A double value. The value return is the price of the item. If the
     * item is invalid, it returns -1.0
     * 
     */
    public double getPrice(TransactionItem item){
        ProductSpec itemSpec=this.store.getProductSpec(item.getUPC());
        if(itemSpec==null){
            return -1.0;
        }else{
            return itemSpec.getPrice();
        }
    }
    
    /**
     * Retrieves the total for the current transaction
     * @return the total amount owed for this transaction. Double value.
     */
    public double getTotal(){
        return this.total;
    }
    
    /**
     * retrieves the IPayment of the customer for the current transaction
     * @return a IPayment object for the current transaction
     */
    public IPayment getPayment(){
        return this.payment;
    }
    
    /**
     * retrieves the amount of change return to the customer for the current 
     * transaction
     * @return the double value of the change the customer will recieve for 
     * the current transaction
     */
    public double getAmountReturned(){
        if("CASH".equals(this.payment.getPaymentType())){
            amountReturned = payment.getAmount() - total;
        }
        return this.amountReturned;
    }
    /**
     * retrieves the subtotal of a transaction item
     * @param index the position the transaction item was processed. starts at index 0.
     * @return a double value of the subtotal of a transaction item. Returns -1
     * if subtotal for item at index does not exist.
     */
    public double getSubTotalAt(int index){
        if(index<this.numTransItemProcessed && index >=0){
            return this.transactionItemSubtotal[index];
        }else{
            return -1.0;
        }
    }
    
    /**
     * retrieves the number of item(s) processed in the current transaction
     * @return The number of item processed in the current transaction. Int value.
     */
    public int getNumTransItemProcessed(){
        return this.numTransItemProcessed;
    }
    
    /**
     * retrieves the sub total of a transaction item
     * @param item the item you wish to get the subtotal for
     * @return a double value of the subtotal for a particular item
     */
    public double getSubTotal(TransactionItem item){
        return (this.getPrice(item)*item.getQuantity());
    }
    
    /**
     * prints all the information about the current transaction to the console
     */
    public void printInvoice(){
        TransactionHeader customerInfo=this.transaction.getTransactionHeader();
        TransactionItem currentItem;
        System.out.println(this.store.getStoreName());
        System.out.println(customerInfo.getCustomerName()+"       "+customerInfo.getDateTime());
        for(int i=0; i<this.numTransItemProcessed; i++){
            currentItem=this.transaction.getTransactionItemsAt(i);
            System.out.printf("%s: %d @ $%.2f     $%.2f\n", currentItem.getUPC(),currentItem.getQuantity(), this.getPrice(currentItem),this.getSubTotalAt(i));
        }
        System.out.println("------");
         System.out.println("Total $"+this.total);
         //System.out.println(this.payment)
        System.out.println("Amount Tendered: "+this.payment.print());
        if(this.payment.authorizePayment()){
            System.out.printf("Amount Returned: $%.2f\n\n", this.getAmountReturned());
        }else{
            System.out.println("Amount Returned: ERROR - UNAUTHORIZED TRANSACTION\n");
        }
    }
    /**
     * @param args the command line arguments
     */
    
    public static void main(String[] args) {
        //initialize the store
        Store store=new Store("Store");
        //initialize manager with the product catalog from the text file
        Manager manager=new Manager(store, new ProductReader("products.txt"));
        //get transaction from the text file
        TransactionReader reader=new TransactionReader(store,"transaction.txt");
        //variables for each transaciton. customer, transaction, transactionheader
        Customer currentCustomer;
        Transaction currentTransaction;
        TransactionHeader transactionInfo;
        //manager opens the store
        manager.open();
        
        //reader each transaction and process each transaction
        while(reader.hasMoreTransactions()){
            //get the transaction
            currentTransaction=reader.getNextTransaction();
            //get the transaction information
            transactionInfo=currentTransaction.getTransactionHeader();
            //create a new customer for this new transaction
             currentCustomer=new Customer(currentTransaction, transactionInfo.getCustomerName());

             //have the customer call the post to process the transaction
            currentCustomer.requestPost(store.getPost());
        }
    }
    
    
}
